﻿#region Class Header
/* ========================================================================
* 【本类功能概述】
* 
* 作者：chinesedragon 
* 时间：4/27/2013 11:37:50 AM
* 文件名：FormReleaseFiles
* 版本：V1.0.1
*
* 修改时间： 
* 修改说明：
* ========================================================================
*/
#endregion


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

namespace Publisher
{
    public partial class FormReleaseFiles : FormBase
    {
        private ProjectInfoClass proInfo;
        private ReleaseList releaseList = null;
        private ExcludeList excludeList = null;
        private readonly string releaseConfigPath;
        private readonly string excludeListPath;
        private int roolLength;
        private int exeFileCount = 0;
        private int iconFileCount = 0;
        private string releasePath = string.Empty;
        private readonly string projectFolder;

        public FormReleaseFiles(ProjectInfoClass pInfo)
        {
            InitializeComponent();
            proInfo = pInfo;

            projectFolder = GlobalValue.MD5(proInfo.pFullPath);
            releaseConfigPath = GlobalValue.ProjectDataPath + "\\"+projectFolder+"\\" + GlobalValue.ReleaseListName;
            excludeListPath = GlobalValue.ProjectDataPath + "\\" + projectFolder + "\\" + GlobalValue.ExcludeListName;
            roolLength = proInfo.pFullPath.Substring(0, proInfo.pFullPath.LastIndexOf("\\")).Length + 1;
        }

        private void FormReleaseFiles_Load(object sender, EventArgs e)
        {
            //读取排除列表
            excludeList = XmlSerializeHelper.LoadObjectFromXml<ExcludeList>(excludeListPath);
            if (excludeList == null)
            {
                excludeList = new ExcludeList();
            }
            //先读取历史发布信息            
            releaseList = XmlSerializeHelper.LoadObjectFromXml<ReleaseList>(releaseConfigPath);
            if (releaseList == null)
            {
                releaseList = new ReleaseList();
                releaseList.AppName = proInfo.pName;
                releaseList.ReleaseVersion = proInfo.pVersion;
                releaseList.ShortcutIcon = proInfo.pIconName;
                releaseList.StartupExec = proInfo.pAssemblyName;
            }

            BindReleaseInfo();
            BindGrid();
        }

        private void BindReleaseInfo()
        {
            textBoxVersion.Text = proInfo.pVersion;
            textBoxSupport.Text = releaseList.SupportUrl;
            textBoxReleaseUrl.Text = releaseList.ReleaseUrl;
            textBoxUserName.Text = releaseList.UserName;
            textBoxUserPassword.Text = releaseList.UserPassword;
            string note = releaseList.ReleaseNote;
            if (!string.IsNullOrEmpty(note))
            {
                note = note.Replace("\n", Environment.NewLine);
            }
            richTextBoxNote.Text = note;
        }

        private void BindGrid()
        {
            //首先获取发布文件下的所有文件列表
            releasePath = proInfo.pFullPath.Substring(0, proInfo.pFullPath.LastIndexOf("\\"));
            releasePath += "\\" + proInfo.pReleaseFolder + "\\";
            roolLength = releasePath.Length;
            List<FileListItem> fileList = GetReleaseFileList(releasePath, true);            
            foreach (FileListItem item in fileList)
            {
                if (Directory.Exists(item.Dir))
                {//this is folder
                    string folderName = "[" + item.Dir.Substring(roolLength) + "]";
                    dataGridViewList.Rows.Add(item.IsSelected, false, false, folderName, "-", "-");
                    DataGridViewRow row = dataGridViewList.Rows[dataGridViewList.Rows.Count - 1];
                    row.Cells[FileName.Name].ReadOnly = true;
                    row.Cells[FileVersion.Name].ReadOnly = true;
                    row.Cells[IsMain.Name].ReadOnly = true;
                    row.Cells[IsIcon.Name].ReadOnly = true;
                    row.Tag = item;
                }
                else
                {//this is file
                    string fileName = item.Dir.Substring(roolLength);
                    FileInfo fi = new FileInfo(item.Dir);
                    string ext = fi.Extension.ToLower();
                    string ver = string.Empty;
                    if (ext == ".exe" || ext == ".dll")
                        ver = FileVersionInfo.GetVersionInfo(item.Dir).FileVersion;
                    if (ext == ".exe")
                        exeFileCount++;
                    if (ext == ".ico")
                        iconFileCount++;
                    bool bMain = !string.IsNullOrEmpty(releaseList.StartupExec) ? releaseList.StartupExec.ToLower() == fileName.ToLower()
                        : exeFileCount == 1;
                    bool bIcon = !string.IsNullOrEmpty(releaseList.ShortcutIcon)
                        ? releaseList.ShortcutIcon.ToLower() == fileName.ToLower() 
                        : (string.IsNullOrEmpty(proInfo.pIconName) && iconFileCount == 1);
                    dataGridViewList.Rows.Add(item.IsSelected, bMain, bIcon, fileName, fi.Length, ver);

                    if (bMain)
                        releaseList.StartupExec = fileName;
                    if (bIcon)
                        releaseList.ShortcutIcon = fileName;

                    DataGridViewRow row = dataGridViewList.Rows[dataGridViewList.Rows.Count - 1];
                    row.Tag = item;
                    if (!string.IsNullOrEmpty(ver))
                    {
                        row.Cells[FileVersion.Name].ReadOnly = true;
                        row.DefaultCellStyle.ForeColor = Color.Gray;
                    }
                    row.Cells[IsMain.Name].ReadOnly = (ext != ".exe");
                    row.Cells[IsIcon.Name].ReadOnly = (ext != ".ico");
                }
            }
            //加入图标
            if (!string.IsNullOrEmpty(proInfo.pIconName))
            {
                string dir = proInfo.pFullPath.Substring(0, proInfo.pFullPath.LastIndexOf("\\") + 1) + proInfo.pIconName;
                var dummy = new FileListItem { Dir = dir, IsSelected = true, IsFile = true };
                fileList.Add(dummy);
                FileInfo fi = new FileInfo(dummy.Dir);
                string ext = fi.Extension.ToLower();
                string fileName = fi.Name;
                if (ext == ".ico")
                    iconFileCount++;
                bool bIcon = !string.IsNullOrEmpty(releaseList.ShortcutIcon)
                        ? releaseList.ShortcutIcon.ToLower() == fileName.ToLower()
                        : iconFileCount <= 1;
                string ver = string.Empty;
                dataGridViewList.Rows.Add(dummy.IsSelected, false, bIcon, proInfo.pIconName, fi.Length, ver);
                if (bIcon)
                    releaseList.ShortcutIcon = proInfo.pIconName;

                DataGridViewRow row = dataGridViewList.Rows[dataGridViewList.Rows.Count - 1];
                row.Tag = dummy;
                if (!string.IsNullOrEmpty(ver))
                {
                    row.Cells[FileVersion.Name].ReadOnly = true;
                    row.DefaultCellStyle.ForeColor = Color.Gray;
                }
                row.Cells[IsMain.Name].ReadOnly = (ext != ".exe");
                row.Cells[IsIcon.Name].ReadOnly = (ext != ".ico");
            }
            //获取非可执行文件的版本
            GetFileVersion();
        }

        private List<FileListItem> GetReleaseFileList(string dir, bool isFirst)
        {
            List<FileListItem> fileList = new List<FileListItem>();
            string shortPath = dir.Substring(roolLength);
            bool folderExcluded = excludeList.ExcludeFolders.Contains(shortPath);
            if (!isFirst)
            {
                FileListItem item = new FileListItem { Dir = dir, IsFile = false, IsSelected = !folderExcluded };
                fileList.Add(item);
            }

            string[] files = Directory.GetFiles(dir);
            foreach (string file in files)
            {
                if (!IsFileExcluded(file))
                {
                    shortPath = file.Substring(roolLength);
                    bool fileExcluded = excludeList.ExcludeFiles.Contains(shortPath);
                    FileListItem item = new FileListItem { Dir = file, IsFile = true, IsSelected = !fileExcluded };
                    fileList.Add(item);
                }
            }

            string[] folders = Directory.GetDirectories(dir);
            foreach (string folder in folders)
            {
                fileList.AddRange(GetReleaseFileList(folder, false));
            }
            return fileList;
        }

        private bool IsFileExcluded(string file)
        {
            string ext = Path.GetExtension(file).ToLower();
            string name = Path.GetFileName(file).ToLower();
            return (ext == ".pdb" || ext == ".log"
                || name.Contains(".vshost.") ||
                name == "updater.exe" || name == "releaselist.xml");
        }

        private void GetFileVersion()
        {
            foreach (DataGridViewRow row in dataGridViewList.Rows)
            {
                string fileName = row.Cells[FileName.Name].Value.ToString().ToLower();
                if (fileName.EndsWith(".exe") || fileName.EndsWith(".dll") || fileName.StartsWith("["))
                    continue;
                bool Versioned = false;
                if (releaseList != null)
                {
                    foreach (ReleaseFile file in releaseList.Files)
                    {
                        if (string.Compare(fileName,file.FileName.ToLower())==0 && !string.IsNullOrEmpty(file.Version))
                        {
                            row.Cells[FileVersion.Name].Value = file.Version;
                            Versioned = true;
                            break;
                        }
                    }
                    if (Versioned)
                        continue;
                    if (!Versioned)
                        row.Cells[FileVersion.Name].Value = "1.0.0.0";
                }

            }
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(textBoxVersion.Text))
            {
                MessageBox.Show("工程发布版本不可为空!");
                textBoxVersion.Focus();
                return;
            }
            if (string.IsNullOrEmpty(textBoxReleaseUrl.Text))
            {
                MessageBox.Show("工程发布网址不可为空!");
                textBoxReleaseUrl.Focus();
                return;
            }
            if (string.IsNullOrEmpty(richTextBoxNote.Text))
            {
                MessageBox.Show("工程发布说明不可为空!");
                richTextBoxNote.Focus();
                return;
            }
            releaseList.ReleaseVersion = textBoxVersion.Text.Trim();
            releaseList.AppName = proInfo.pName;
            releaseList.ReleaseDate = DateTime.Now.ToString();
            releaseList.ReleaseUrl = textBoxReleaseUrl.Text;
            releaseList.UserName = textBoxUserName.Text;
            releaseList.UserPassword = textBoxUserPassword.Text;
            releaseList.SupportUrl = textBoxSupport.Text;
            releaseList.ReleaseNote = richTextBoxNote.Text;

            List<ReleaseFile> files = new List<ReleaseFile>();
            int mainCount = 0;
            int iconCount = 0;
            excludeList.ExcludeFiles.Clear();
            excludeList.ExcludeFolders.Clear();
            foreach (DataGridViewRow row in dataGridViewList.Rows)
            {
                row.DefaultCellStyle.BackColor = SystemColors.Window;
                bool bSelected = Convert.ToBoolean(row.Cells[IsSelected.Name].Value);
                if (!bSelected)     //没有选择要发布
                {
                    //记录排除列表
                    string exFileName = row.Cells[FileName.Name].Value.ToString();
                    if (exFileName.StartsWith("["))
                        excludeList.ExcludeFolders.Add(exFileName.TrimStart('[').TrimEnd(']'));
                    else
                        excludeList.ExcludeFiles.Add(exFileName);
                    continue;
                }
                string fileName = row.Cells[FileName.Name].Value.ToString();
                if (fileName.StartsWith("["))   //是目录
                    continue;

                if (row.Cells[FileVersion.Name].Value == null 
                    || string.IsNullOrEmpty(row.Cells[FileVersion.Name].Value.ToString()))
                {
                    MessageBox.Show(fileName + " 没有版本号吗?");
                    dataGridViewList.FirstDisplayedScrollingRowIndex = row.Index;
                    row.DefaultCellStyle.BackColor = Color.Yellow;
                    return;
                }
                string ver = row.Cells[FileVersion.Name].Value.ToString();
                bool bMain = Convert.ToBoolean(row.Cells[IsMain.Name].Value);
                if (bMain)
                {
                    mainCount++;
                    releaseList.StartupExec = fileName;
                }
                bool bIcon = Convert.ToBoolean(row.Cells[IsIcon.Name].Value);
                if (bIcon)
                {
                    iconCount++;
                    releaseList.ShortcutIcon = fileName;
                }

                ReleaseFile file = new ReleaseFile
                {
                    FileName = fileName,
                    FileSize = long.Parse(row.Cells[FileSize.Name].Value.ToString()),
                    Version = ver,
                };
                files.Add(file);
            }
            //判断主程序是否选择
            if (mainCount == 0)
            {
                MessageBox.Show("亲，您至少得选一个主程序吧！");
                return;
            }
            if (mainCount > 1)
            {
                MessageBox.Show("亲，您只能选一个主程序哦！");
                return;
            }
            //判断图标是否多于1个
            if (iconCount > 1)
            {
                MessageBox.Show("亲，您只能选一个主程序图标哦！");
                return;
            }
            if (iconCount == 0)
            {
                releaseList.ShortcutIcon = string.Empty;
            }

            releaseList.Files = files;

            CopyFiles();

            //保存ReleaseList记录
            string proFolder = Path.Combine(GlobalValue.ProjectDataPath, projectFolder);
            if (!Directory.Exists(proFolder))
                Directory.CreateDirectory(proFolder);
            XmlSerializeHelper.SaveXmlFormObject(proFolder + "\\" + GlobalValue.ReleaseListName, releaseList);
            //保存Exclude记录
            XmlSerializeHelper.SaveXmlFormObject(proFolder + "\\" + GlobalValue.ExcludeListName, excludeList);
            //保存ProjectInfo记录
            XmlSerializeHelper.SaveXmlFormObject(proFolder + "\\" + GlobalValue.ProjectInfoName, proInfo);

            //显示发布界面
            FormRelease formRelease = new FormRelease(proInfo, releaseList);
            this.Hide();
            formRelease.ShowDialog(this);
        }

        private void CopyFiles()
        {
            DirectoryInfo di = new DirectoryInfo(releasePath);
            string publishFolder = Path.Combine(di.Parent.FullName, "publish");
            if (Directory.Exists(publishFolder))
                Directory.Delete(publishFolder, true);
            Directory.CreateDirectory(publishFolder);
            string versionFolder = Path.Combine(publishFolder, releaseList.ReleaseVersion);
            if (Directory.Exists(versionFolder))
                Directory.Delete(versionFolder, true);
            Directory.CreateDirectory(versionFolder);

            foreach (DataGridViewRow row in dataGridViewList.Rows)
            {
                bool bSelected = Convert.ToBoolean(row.Cells[IsSelected.Name].Value);
                if (!bSelected)
                    continue;
                string fileName = row.Cells[FileName.Name].Value.ToString();
                if (fileName.StartsWith("["))
                    continue;
                string sourceFile = (row.Tag as FileListItem).Dir;
                string targetFile = string.Concat(versionFolder, "\\" + fileName);
                string targetDir = Path.GetDirectoryName(targetFile);
                if (!Directory.Exists(targetDir))
                    Directory.CreateDirectory(targetDir);
                File.Copy(sourceFile, targetFile, true);
            }
            //检查是否存在Updater.exe
            string updaterFile = Path.Combine(di.FullName, "Updater.exe");
            if (File.Exists(updaterFile))
            {
                string updaterFile2 = Path.Combine(versionFolder, "Updater.exe");
                File.Copy(updaterFile, updaterFile2, true);
            }

            string publishReleaseList = Path.Combine(versionFolder, GlobalValue.ReleaseListName);
            XmlSerializeHelper.SaveXmlFormObject(publishReleaseList, releaseList);
            string publishList = Path.Combine(publishFolder, GlobalValue.ReleaseListName);
            XmlSerializeHelper.SaveXmlFormObject(publishList, releaseList);
        }

        private void dataGridViewList_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (dataGridViewList.CurrentCell != null && dataGridViewList.CurrentCell.ReadOnly)
            {
                return;
            }
            switch (e.ColumnIndex)
            {
                case 0:
                    {
                        bool bSelect = !Convert.ToBoolean(dataGridViewList.CurrentCell.Value);
                        dataGridViewList.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = bSelect; //先给自己赋值
                        string dir = GetRowDir(e.RowIndex);
                        if (Directory.Exists(dir))  //选中的是文件夹，则此文件夹下的所有文件为选中或不选中状态
                        {
                            for (int i = e.RowIndex + 1; i < dataGridViewList.Rows.Count; ++i)
                            {
                                string path = GetRowDir(i);
                                if (!path.StartsWith(dir))
                                {
                                    break;
                                }
                                dataGridViewList.Rows[i].Cells[IsSelected.Name].Value = bSelect;
                            }
                        }
                        else    //选中的是文件，则只有上层的文件夹会被选中
                        {
                            if (bSelect)    //只有当选中时才查找上层文件夹
                            {
                                for (int i = e.RowIndex - 1; i >= 0; --i)
                                {
                                    string path = GetRowDir(i);
                                    if (Directory.Exists(path))     //是文件夹
                                    {
                                        if (dir.StartsWith(path))
                                        {
                                            dataGridViewList.Rows[i].Cells[IsSelected.Name].Value = bSelect;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    break;
                case 1:
                case 2://只能选择一个
                    {
                        bool bSelect = !Convert.ToBoolean(dataGridViewList.CurrentCell.Value);
                        dataGridViewList.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = bSelect; //先给自己赋值
                        if (!bSelect)
                            break;
                        foreach (DataGridViewRow row in dataGridViewList.Rows)
                        {
                            if (row.Index != e.RowIndex)
                            {
                                row.Cells[e.ColumnIndex].Value = false;
                            }
                        }
                        dataGridViewList.Rows[e.RowIndex].Cells[IsSelected.Name].Value = true;
                    }
                    break;
            }
        }

        private string GetRowDir(int i)
        {
            return (dataGridViewList.Rows[i].Tag as FileListItem).Dir;
        }
    }
}
